package com.atguigu.exam.service.impl;


import com.atguigu.exam.entity.Category;
import com.atguigu.exam.entity.Question;
import com.atguigu.exam.exception.ExamException;
import com.atguigu.exam.mapper.CategoryMapper;
import com.atguigu.exam.mapper.QuestionMapper;
import com.atguigu.exam.service.CategoryService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Slf4j
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {

    @Autowired
    private QuestionMapper questionMapper;

    @Override
    public List<Category> getCategoryList() {
        //获取所有的分类，并按照sort升序排序
        List<Category> categoryList = baseMapper.selectList(new LambdaQueryWrapper<Category>().orderByAsc(Category::getSort));
        //调用设置分类下题目数量的方法
        addCategoryQuestionCount(categoryList);
        return categoryList;
    }


    //给每个分类添加题目数量的方法
    public void addCategoryQuestionCount(List<Category> categoryList) {
        //获取每个分类对应的题目的数量
        List<Map<Long, Long>> questionCount = questionMapper.getCategoryCount();
        //将 List<Map<Long,Long>>转换为Map<Long,Long>
        Map<Long, Long> categroyIdMap = questionCount.stream().collect(Collectors.toMap(
                map -> map.get("categoryId"),
                map -> map.get("count")
        ));
        //遍历所有的分类
        categoryList.forEach(category -> {
            //根据分类id从categroyIdMap中获取该分类下的题目数量
            Long count = categroyIdMap.getOrDefault(category.getId(), 0L);
            //将当前分类下的题目数量设置到分类中
            category.setCount(count);
        });
    }

    @Override
    public List<Category> getCategoryTree() {
        //获取所有的分类，并按照sort排序
        List<Category> categoryList = baseMapper.selectList(new LambdaQueryWrapper<Category>().orderByAsc(Category::getSort));
        //调用给分类添加题目数量的方法
        addCategoryQuestionCount(categoryList);
        //构建分类树的方法
        List<Category> firstLevelCategory = buildCategoryTree(categoryList);
        return firstLevelCategory;
    }

    private List<Category> buildCategoryTree(List<Category> categoryList) {
        //根据parentId分组获取每个分类下的子分类列表
        Map<Long, List<Category>> parentIdChildrenMap = categoryList.stream().collect(Collectors.groupingBy(Category::getParentId));
        //遍历所有的分类
        categoryList.forEach(category -> {
            //获取当前分类的id
            Long categoryId = category.getId();
            //从categoryMap中获取当前分类的子分类列表
            List<Category> childrenCategory = parentIdChildrenMap.getOrDefault(categoryId, new ArrayList<>());
            //给当前分类设置孩子
            category.setChildren(childrenCategory);
            //获取所有子分类中题目数量总和
            Long childrenSumCount = childrenCategory.stream().mapToLong(Category::getCount).sum();
            //获取当前分类的题目数量
            Long currentCount = category.getCount();
            //重新设置当前分类的题目数量
            category.setCount(currentCount + childrenSumCount);
        });
        //获取所有parentId为0的分类
        List<Category> firstLevelCategory = categoryList.stream().filter(category -> category.getParentId() == 0).collect(Collectors.toList());
        return firstLevelCategory;
    }


    @Override
    public void addCategory(Category category) {
        //判断新的分类在当前父分类中是否已经存在
        //根据输入的新的分类的名字和parent_id查询新添加的分类是否已经存在
        //创建LambdaQuerWrapper对象
        LambdaQueryWrapper<Category> categoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //封装查询条件
        // WHERE name = ? AND parent_id = ?
        // 查询 “名称等于当前分类名称，且父分类 ID 等于当前分类父 ID” 的记录。
        categoryLambdaQueryWrapper.eq(Category::getName, category.getName())
                .eq(Category::getParentId, category.getParentId());

        //调用baseMapper中exists方法
        boolean exists = baseMapper.exists(categoryLambdaQueryWrapper);//若存在匹配的记录则返回 true，否则返回 false。
        if (exists) {
            //获取父分类
            Category parentCategory = baseMapper
                    .selectById(category.getParentId());
            //证明在当前分类的父分类下已经存在该分类名称
            throw new ExamException
                    (444, "在父分类<" + parentCategory.getName() + ">下已经存在 '" + category.getName() + "'");
        }
        //可以添加该分类
        baseMapper.insert(category);
    }

    @Override
    public void updateCategory(Category category) {
        //更新分类的时候不能更新为该父分类下其他分类的名称
        //查询条件：名字和父id等于非自己的其他分类的名字和父id
        boolean exists = baseMapper
                .exists(new LambdaQueryWrapper<Category>()
                        .eq(Category::getName, category.getName())
                        .eq(Category::getParentId, category.getParentId())
                        .ne(Category::getId, category.getId()));//“不等于”（≠）的查询条件
        if (exists) {
            //该分类名已经存在
            //获取父分类
            Category parentCategory = baseMapper
                    .selectById(category.getParentId());
            //证明在当前分类的父分类下已经存在该分类名称
            throw new ExamException(444, "在父分类<" + parentCategory.getName() + ">下已经存在 '" + category.getName() + "'，请修改一个其他分类名");
        }
        //可以更新分类名
        category.setUpdateTime(new Date());
        baseMapper.updateById(category);
    }

    @Override
    public void deleteCategory(Long id) {
        //判断当前分类下是否有子分类
        Long count = baseMapper.selectCount(new LambdaQueryWrapper<Category>().eq(Category::getParentId, id));
        if (count > 0) {
            //该分类下有子分类，不能删除
            throw new ExamException(555, "该分类下有子分类，不能删除");
        }
        //判断当前分类下是否有题目
        Long count1 = questionMapper.selectCount(new LambdaQueryWrapper<Question>().eq(Question::getCategoryId, id));
        if (count1 > 0) {
            //该分类下有题，不能删除
            throw new ExamException(666, "该分类下有题目，不能删除");
        }
        //调用根据id删除的方法
        baseMapper.deleteById(id);
    }


}